package com.youhome.service.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.mts.model.v20140618.QueryJobListRequest;
import com.aliyuncs.mts.model.v20140618.QueryJobListResponse;
import com.aliyuncs.mts.model.v20140618.SubmitJobsRequest;
import com.aliyuncs.mts.model.v20140618.SubmitJobsResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.youhome.common.config.OSSConfig;
import com.youhome.common.config.VideoConfig;
import com.youhome.common.config.WatermarkConfig;
import com.youhome.common.exception.CustomException;
import com.youhome.common.response.ResultCode;
import com.youhome.service.mapper.HouseVideoMapper;
import com.youhome.service.mapper.VideoTranscodingMapper;
import com.youhome.service.model.HouseVideo;
import com.youhome.service.model.VideoTranscoding;
import com.youhome.service.service.VideoTransCodingService;
import com.youhome.utils.HttpClientUtils;
import com.youhome.utils.SignUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Created by chen365 on 2019/01/16.
 */
@Service
public class VideoTransCodingServiceImpl implements VideoTransCodingService {

    @Autowired
    private VideoTranscodingMapper videoTranscodingMapper;
    @Autowired
    private HouseVideoMapper houseVideoMapper;
    @Autowired
    private OSSConfig ossConfig;
    @Autowired
    private VideoConfig videoConfig;
    @Autowired
    private WatermarkConfig watermarkConfig;
    /*
    public static void main(String[] args) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date d1 = df.parse("2004-03-26 13:55:40");
            Date d2 = df.parse("2004-03-26 13:30:24");
            long diff = d1.getTime() - d2.getTime();//这样得到的差值是毫秒级别
            System.err.println(diff / 1000 / 60);
            long days = diff / (1000 * 60 * 60 * 24);

            long hours = (diff - days * (1000 * 60 * 60 * 24)) / (1000 * 60 * 60);
            long minutes = (diff - days * (1000 * 60 * 60 * 24) - hours * (1000 * 60 * 60)) / (1000 * 60);
            System.out.println("" + days + "天" + hours + "小时" + minutes + "分");
        } catch (Exception e) {
        }
    }

    */

    @Override
    public void to() {
        //==================================1080 转==================================================
//        transcoding("Test-1080","Altair_Alara_new.mp4","640","640");
//        transcoding("Test-1080","Altair_Alara_new.mp4","640","720");
//
//        transcoding("Test-1080","Altair_Alara_new.mp4","720","640");
//        transcoding("Test-1080","Altair_Alara_new.mp4","720","720");
//
//        transcoding("Test-1080","Altair_Alara_new.mp4","800","640");
//        transcoding("Test-1080","Altair_Alara_new.mp4","800","720");
//
//        transcoding("Test-1080","Altair_Alara_new.mp4","1000","640");
//        transcoding("Test-1080","Altair_Alara_new.mp4","1000","720");
//
//        transcoding("Test-1080","Altair_Alara_new.mp4","2000","640");
//        transcoding("Test-1080","Altair_Alara_new.mp4","2000","720");

        //==================================720 转==================================================
//
//        transcoding("Test-720", "720.mp4", "640", "640");
//        transcoding("Test-720", "720.mp4", "640", "720");
//
//        transcoding("Test-720", "720.mp4", "720", "640");
//        transcoding("Test-720", "720.mp4", "720", "720");
//
//        transcoding("Test-720", "720.mp4", "800", "640");
//        transcoding("Test-720", "720.mp4", "800", "720");
//
//        transcoding("Test-720", "720.mp4", "1000", "640");
//        transcoding("Test-720", "720.mp4", "1000", "720");
//
//        transcoding("Test-720", "720.mp4", "2000", "640");
//        transcoding("Test-720", "720.mp4", "2000", "720");


        //==================================640 转==================================================

//        transcoding("Test-640","640.mp4","640","640");
//        transcoding("Test-640","640.mp4","640","720");
//
//        transcoding("Test-640","640.mp4","720","640");
//        transcoding("Test-640","640.mp4","720","720");
//
//        transcoding("Test-640","640.mp4","800","640");
//        transcoding("Test-640","640.mp4","800","720");
//
//        transcoding("Test-640","640.mp4","1000","640");
//        transcoding("Test-640","640.mp4","1000","720");
//
//        transcoding("Test-640","640.mp4","2000","640");
//        transcoding("Test-640","640.mp4","2000","720");


        //==================================480 转==================================================

        transcoding("Test-480", "480.mp4", "640", "640");
        transcoding("Test-480", "480.mp4", "640", "720");

        transcoding("Test-480", "480.mp4", "720", "640");
        transcoding("Test-480", "480.mp4", "720", "720");

        transcoding("Test-480", "480.mp4", "800", "640");
        transcoding("Test-480", "480.mp4", "800", "720");

        transcoding("Test-480", "480.mp4", "1000", "640");
        transcoding("Test-480", "480.mp4", "1000", "720");

        transcoding("Test-480", "480.mp4", "2000", "640");
        transcoding("Test-480", "480.mp4", "2000", "720");

    }

    @Override
    public void search() {
        for (VideoTranscoding item : videoTranscodingMapper.selectByAll()) {

            // 创建API请求并设置参数
            QueryJobListRequest request = new QueryJobListRequest();
            QueryJobListResponse response;
            // 转码作业ID列表，逗号分隔，一次最多10个
            request.setJobIds(item.getJobId());
            // 发起请求并处理应答或异常
            try {
                response = getIAcsClient().getAcsResponse(request);

                QueryJobListResponse.Job job = response.getJobList().get(0);

                VideoTranscoding record = new VideoTranscoding();

                record.setId(item.getId());
                record.setStatus(job.getState());

                String fileSize = job.getOutput().getProperties().getFileSize();
                double size = Double.valueOf(fileSize) / 1024 / 1024;

                BigDecimal bg = new BigDecimal(size);
                size = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

                record.setSize(size);

                Object o = JSONObject.toJSON(job);

                System.err.println(o.toString());

                videoTranscodingMapper.updateByPrimaryKeySelective(record);

            } catch (ServerException e) {
                e.printStackTrace();
            } catch (ClientException e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public void countTime() {
        for (VideoTranscoding item : videoTranscodingMapper.selectByAll()) {
            VideoTranscoding record = new VideoTranscoding();
            Date finishTime = item.getFinishTime();
            Date createTime = item.getCreateTime();
            if (!StringUtils.isEmpty(finishTime) && !StringUtils.isEmpty(createTime)) {

                long diff = finishTime.getTime() - createTime.getTime();//这样得到的差值是毫秒级别
                record.setId(item.getId());
                record.setTime((double) (diff / 1000 / 60));
                videoTranscodingMapper.updateByPrimaryKeySelective(record);
            }
        }
    }

    @Override
    public void transCoding(String houseId, String name, Double size, String url) throws CustomException {
        if (StringUtils.isEmpty(houseId) || StringUtils.isEmpty(url)) {
            throw new CustomException(ResultCode.ERROR_PARAMETER);
        }
        Integer bitrate = 1000;
        Integer width = 640;
        Integer fps = 25;
        // Oss region / 输出Bucket所在地域
        String OssLocation = "oss-cn-hangzhou";
        // Oss bucket / 输出Bucket
        String OssInputBucket = "imf-video";

        // Oss bucket / 输出Bucket
        String OssOutBucket = "imf-video-export";

        // Oss Input Object / 输入文件名,路径
        String OssInputObject = url;

        // Oss Output Object / 输出文件名,路径
        String OssOutputObject = "video/" + UUID.randomUUID().toString().toLowerCase() + ".mp4";

        // Pipeline Id / 管道ID
        String PipelineId = "3d1380e113314ac4acd10da250322b93";
        //水印模版ID
        String watermarkTemplateId = "bfe08e838eb44df283b6e2a7a16aa1d7";

        String imageWatermarkObject = "watermark/logo.png";

        // 创建API请求并设置参数
        SubmitJobsRequest request = new SubmitJobsRequest();
        // Input / 作业输入，JSON对象
        JSONObject input = new JSONObject();
        input.put("Location", OssLocation);
        input.put("Bucket", OssInputBucket);

        try {
            input.put("Object", URLEncoder.encode(OssInputObject, "utf-8"));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("input URL encode failed");
        }
        request.setInput(input.toJSONString());
        // Output / Outputs由Output列表构成，JSON数组，大小上限为30
        String outputOSSObject;

        try {
            outputOSSObject = URLEncoder.encode(OssOutputObject, "utf-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("output URL encode failed");
        }

        JSONObject imageWatermarkInput = new JSONObject();
        imageWatermarkInput.put("Location", OssLocation);
        imageWatermarkInput.put("Bucket", OssInputBucket);
        try {
            imageWatermarkInput.put("Object", URLEncoder.encode(imageWatermarkObject, "utf-8"));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("imageWatetmark Input URL encode failed");
        }

        JSONObject output = new JSONObject();
        output.put("OutputObject", outputOSSObject);
        // Ouput->Container / 输出的容器类型（文件格式）。视频支持mp4、flv、ts、m3u8，音频支持mp3、mp4等。
        JSONObject container = new JSONObject();
        container.put("Format", "mp4");
        output.put("Container", container.toJSONString());
        // Ouput->Video / 输出的视频参数。例如编码格式、码率、宽、高、帧率等。
        // https://help.aliyun.com/document_detail/29226.html?spm=a2c4g.11186623.6.628.VcmQDE
        JSONObject video = new JSONObject();
        video.put("Codec", "H.264");
        video.put("Bitrate", bitrate);
        video.put("Width", width);
        video.put("Fps", fps);
        output.put("Video", video.toJSONString());

        // Ouput->Audio / 输出的音频参数
        JSONObject audio = new JSONObject();
        audio.put("Codec", "AAC");
        audio.put("Bitrate", "128");
        audio.put("Channels", "2");
        audio.put("Samplerate", "44100");

        //output.put("Audio", audio.toJSONString());
        // Ouput->TemplateId / 输出的模板参数
        //output.put("TemplateId", TemplateId);

        JSONObject imageWatermark = new JSONObject();
        //imageWatermark.put("WaterMarkTemplateId", watermarkTemplateId);
        imageWatermark.put("Type", "Image");
        imageWatermark.put("InputFile", imageWatermarkInput);
        imageWatermark.put("ReferPos", "TopLeft");
        //imageWatermark.put("Width", "0.05");
        imageWatermark.put("Dx", "20");
        imageWatermark.put("Dy", "20");

        // Output->Watermarks
        JSONArray watermarks = new JSONArray();
        watermarks.add(imageWatermark);

        output.put("WaterMarks", watermarks.toJSONString());

        JSONArray outputs = new JSONArray();
        outputs.add(output);
        request.setOutputs(outputs.toJSONString());
        request.setOutputBucket(OssOutBucket);
        request.setOutputLocation(OssLocation);
        // PipelineId / 管道ID。若需要异步通知，须保证此管道绑定了可用的消息主题
        request.setPipelineId(PipelineId);

        // 发起请求并处理应答或异常
        SubmitJobsResponse response;
        try {

            response = getIAcsClient().getAcsResponse(request);
            SubmitJobsResponse.JobResult jobResult = response.getJobResultList().get(0);
            System.out.println("RequestId :" + response.getRequestId());
            SubmitJobsResponse.JobResult.Job job = jobResult.getJob();
            String jobId = job.getJobId();

            String videoId = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
            HouseVideo record = new HouseVideo();
            record.setVideoId(videoId);
            record.setHouseId(houseId);
            record.setJobId(jobId);
            record.setCreateTime(new Date());
            record.setVideoOriginalUrl(url);
            record.setVideoOriginalSize(size);
            record.setVideoName(name);
            record.setVideoUrl(OssOutputObject);
            record.setStatus(job.getState());
            record.setEnabled(true);

            houseVideoMapper.insertSelective(record);

            //截图
            cover(videoId, url);

            if (response.getJobResultList().get(0).getSuccess()) {
                System.out.println("JobId :" + jobId);
            } else {
                System.out.println("SubmitJobs Failed Code :" + response.getJobResultList().get(0).getCode() + " Message:" + response.getJobResultList().get(0).getMessage());
            }
        } catch (ServerException e) {
            e.printStackTrace();
            throw new CustomException(ResultCode.ERROR);
        } catch (ClientException e) {
            e.printStackTrace();
            throw new CustomException(ResultCode.ERROR);
        }

    }


    /**
     * 创建DefaultAcsClient实例并初始化
     *
     * @return IAcsClient
     */
    private IAcsClient getIAcsClient() {
        DefaultProfile profile = DefaultProfile.getProfile(
                "cn-hangzhou",// 地域ID
                "LTAIcfXDvwDqTETw",// 您的AccessKey ID
                "z2vkfxsGTdys7zoPqNd0qnh8XRpWwI"// 您的AccessKey Secret
        );
        return new DefaultAcsClient(profile);
    }

    public void transcoding(String type, String source, String bitrate, String width) {
        // Params

        // Oss region / 输出Bucket所在地域
        String OssLocation = "oss-cn-hangzhou";
        // Oss bucket / 输出Bucket
        String OssBucket = "imf-video";

        // Oss Input Object / 输入文件名,路径
        String OssInputObject = "source/" + source;


        // Oss Output Object / 输出文件名,路径
        //String OssOutputObject = "video/"+ DateFormatUtils.format(new Date(),"yyyyMMddHHmmSSS")+".mp4";
        String OssOutputObject = null;

        OssOutputObject = "export/" + type + "p_to_m" + bitrate + "_" + width + "p.mp4";

        // Template Id / 输出模板ID(转码模版ID)
        String TemplateId = "a14d9facc95a461486270797b5323b72"; //3500
        // Pipeline Id / 管道ID
        String PipelineId = "3d1380e113314ac4acd10da250322b93";
        //水印模版ID
        String watermarkTemplateId = "bfe08e838eb44df283b6e2a7a16aa1d7";

        String imageWatermarkObject = "logo.png";

        // 创建API请求并设置参数
        SubmitJobsRequest request = new SubmitJobsRequest();
        // Input / 作业输入，JSON对象
        JSONObject input = new JSONObject();
        input.put("Location", OssLocation);
        input.put("Bucket", OssBucket);

        try {
            input.put("Object", URLEncoder.encode(OssInputObject, "utf-8"));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("input URL encode failed");
        }
        request.setInput(input.toJSONString());
        // Output / Outputs由Output列表构成，JSON数组，大小上限为30

        String outputOSSObject;

        try {
            outputOSSObject = URLEncoder.encode(OssOutputObject, "utf-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("output URL encode failed");
        }

        JSONObject imageWatermarkInput = new JSONObject();
        imageWatermarkInput.put("Location", OssLocation);
        imageWatermarkInput.put("Bucket", OssBucket);
        try {
            imageWatermarkInput.put("Object", URLEncoder.encode(imageWatermarkObject, "utf-8"));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("imageWatetmark Input URL encode failed");
        }

        JSONObject output = new JSONObject();
        output.put("OutputObject", outputOSSObject);
        // Ouput->Container / 输出的容器类型（文件格式）。视频支持mp4、flv、ts、m3u8，音频支持mp3、mp4等。
        JSONObject container = new JSONObject();
        container.put("Format", "mp4");
        output.put("Container", container.toJSONString());
        // Ouput->Video / 输出的视频参数。例如编码格式、码率、宽、高、帧率等。
        // https://help.aliyun.com/document_detail/29226.html?spm=a2c4g.11186623.6.628.VcmQDE
        JSONObject video = new JSONObject();
        video.put("Codec", "H.264");
        video.put("Bitrate", bitrate);
        video.put("Width", width);
        video.put("Fps", "25");
        output.put("Video", video.toJSONString());

        // Ouput->Audio / 输出的音频参数
        JSONObject audio = new JSONObject();
        audio.put("Codec", "AAC");
        audio.put("Bitrate", "128");
        audio.put("Channels", "2");
        audio.put("Samplerate", "44100");

        //output.put("Audio", audio.toJSONString());

        // Ouput->TemplateId / 输出的模板参数
        //output.put("TemplateId", TemplateId);


        JSONObject imageWatermark = new JSONObject();
        imageWatermark.put("WaterMarkTemplateId", watermarkTemplateId);
        imageWatermark.put("Type", "Image");
        imageWatermark.put("InputFile", imageWatermarkInput);
        imageWatermark.put("ReferPos", "TopRight");
        //imageWatermark.put("Width", "0.05");
        imageWatermark.put("Dx", "0");
        imageWatermark.put("Dy", "0");

        // Output->Watermarks
        JSONArray watermarks = new JSONArray();
        watermarks.add(imageWatermark);


        output.put("WaterMarks", watermarks.toJSONString());

        JSONArray outputs = new JSONArray();
        outputs.add(output);
        request.setOutputs(outputs.toJSONString());
        request.setOutputBucket(OssBucket);
        request.setOutputLocation(OssLocation);
        // PipelineId / 管道ID。若需要异步通知，须保证此管道绑定了可用的消息主题
        request.setPipelineId(PipelineId);

        // 发起请求并处理应答或异常
        SubmitJobsResponse response;
        try {

            response = getIAcsClient().getAcsResponse(request);
            SubmitJobsResponse.JobResult jobResult = response.getJobResultList().get(0);
            System.out.println("RequestId :" + response.getRequestId());
            SubmitJobsResponse.JobResult.Job job = response.getJobResultList().get(0).getJob();
            String jobId = job.getJobId();

            VideoTranscoding record = new VideoTranscoding();

            record.setJobId(jobId);
            record.setType(type);
            record.setSource(source);
            record.setCreateTime(new Date());
            record.setBitrate(bitrate);
            record.setWidth(width);
            record.setVideo(OssOutputObject);
            record.setStatus(job.getState());

            videoTranscodingMapper.insertSelective(record);

            if (response.getJobResultList().get(0).getSuccess()) {

                System.out.println("JobId :" + jobId);
                //searchStatusByJobId(jobId);
            } else {
                System.out.println("SubmitJobs Failed Code :" + response.getJobResultList().get(0).getCode() + " Message:" + response.getJobResultList().get(0).getMessage());
            }
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
    }


    /**
     * 视频截图
     *
     * @param videoId          视频ID
     * @param videoOriginalUrl 视频原文件
     */
    public void cover(String videoId, String videoOriginalUrl) {
        String accessKeyId = ossConfig.getAccessKeyId();
        String keySecret = ossConfig.getAccessKeySecret();

        // Oss region / 输出Bucket所在地域
        String OssLocation = "oss-cn-hangzhou";
        // Oss bucket / 输出Bucket
        String OssInputBucket = "imf-video";
        String OssOutBucket = "imf-video-export";

        // Pipeline Id / 管道ID
        String PipelineId = "3d1380e113314ac4acd10da250322b93";

        //截图存在地址
        String coverUrl = "cover/" + UUID.randomUUID().toString().replaceAll("-", "").toLowerCase() + ".jpg";


        Map<String, String> parameterMap = new HashMap<>();
        // 加入请求公共参数
        parameterMap.put("Action", "SubmitSnapshotJob");

        //{"Bucket":"example-bucket", "Location": "oss-cn-hangzhou","Object":"example.flv" }

        JSONObject input = new JSONObject();
        input.put("Location", OssLocation);
        input.put("Bucket", OssInputBucket);

        try {
            input.put("Object", URLEncoder.encode(videoOriginalUrl, "utf-8"));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("input URL encode failed");
        }

        parameterMap.put("Input", input.toJSONString());

//        {
//            "OutputFile":{"Bucket":"example-001", "Location":"oss-cn-hangzhou", "Object":"example.jpg"},
//            "Time":"5"
//        }

        JSONObject snapshotConfig = new JSONObject();

        JSONObject out = new JSONObject();
        out.put("Location", OssLocation);
        out.put("Bucket", OssOutBucket);

        try {
            out.put("Object", URLEncoder.encode(coverUrl, "utf-8"));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("input URL encode failed");
        }
        snapshotConfig.put("OutputFile", out.toJSONString());
        snapshotConfig.put("Time", 5); //截图开始时间
        parameterMap.put("SnapshotConfig", snapshotConfig.toJSONString());

        parameterMap.put("PipelineId", PipelineId);
        //parameterMap.put("UserData", item.getJobId()); //用户自定义数据

        parameterMap.put("Format", "JSON");
        parameterMap.put("Version", "2014-06-18");
        parameterMap.put("AccessKeyId", accessKeyId);
        parameterMap.put("SignatureMethod", "HMAC-SHA1");
        parameterMap.put("Timestamp", SignUtils.formatIso8601Date(new Date()));
        parameterMap.put("SignatureVersion", "1.0");
        parameterMap.put("SignatureNonce", UUID.randomUUID().toString());

        try {
            String url = SignUtils.sign(keySecret, parameterMap);
            String json = HttpClientUtils.sendGet(url);
            if (!org.apache.commons.lang3.StringUtils.isEmpty(json)) {
                HouseVideo record = new HouseVideo();
                record.setVideoId(videoId);
                record.setCoverUrl(coverUrl);
                record.setUpdateTime(new Date());
                houseVideoMapper.updateByPrimaryKeySelective(record);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }


    }

}
